/*
 * @Author: lll 1280388921@qq.com
 * @Date: 2025-04-13 22:49:21
 * @LastEditors: lll 1280388921@qq.com
 * @LastEditTime: 2025-04-14 12:06:57
 * @FilePath: /lesson28/log.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once

#include <iostream>
#include <stdarg.h>
#include <time.h>
#include<unistd.h>
#include<cstdlib>
#include<cerrno>
#include<cstring>
#include<string>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>

using namespace std;

#define SIZE 1024

#define Info    0
#define Debug   1
#define Warming 2
#define Error   3
#define Fatal   4

#define Screen      1
#define Onefile     2
#define Classfile   3

#define Logfile "log.txt"

class Log
{
public:
    Log()
    {
        PrintMethod=Screen;
        path="./log/";
    }
    void Enable(int method)
    {
        PrintMethod=method;
    }
    string leveltostring(int level)
    {
        switch (level)
        {
        case Info:
            return "Info";
        case Debug:
            return "Debug";
        case Warming:
            return "Warming";
        case Error:
            return "Error";
        case Fatal:
            return "Fatal";
        default:
            return "None";
        }
    }

    // void logmsg(int level, char *format, ...)
    // {
    //     time_t t = time(nullptr);
    //     struct tm *ctime = localtime(&t);

    //     char lbuffer[SIZE];
    //     snprintf(lbuffer, sizeof(lbuffer), "[%s][%d-%d-%d %d:%d:%d]", leveltostring(level).c_str(),
    //              ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
    //              ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

    //     va_list s;
    //     va_start(s, format);
    //     char rbuffer[SIZE];
    //     vsnprintf(rbuffer, sizeof(rbuffer), format, s);
    //     va_end(s);

    //     // 格式：默认部分（具体参数部分）+自定义部分（可变参数部分）
    //     char logtxt[SIZE * 2];
    //     snprintf(logtxt, sizeof(logtxt), "%s %s", lbuffer, rbuffer);

    //     printLog(level,logtxt);
    // }

    void printLog(int level,string logtxt)
    {
        switch (PrintMethod)
        {
            case Screen:
                cout<<logtxt<<endl;
                break;
            case Onefile:
                printOnefile(Logfile,logtxt);
                break;
            case Classfile:
                printClassfile(level,logtxt);
                break;
            default:
                break;
        }
    }

    void printOnefile(const string&logname,const string &logtxt)
    {
        string _logname=path+logname;
        int fd=open(_logname.c_str(),O_WRONLY|O_CREAT|O_APPEND,0666);//log.txt
        if(fd<0)return;
        write(fd,logtxt.c_str(),logtxt.size());
        close(fd);
    }
    void printClassfile(int level,const string &logtxt)
    {
        string filename=Logfile;
        filename+=".";
        filename+=leveltostring(level);//log.txt.Info/Warming...
        printOnefile(filename,logtxt);
    }

    void operator()(int level, char *format, ...)
    {
        time_t t = time(nullptr);
        struct tm *ctime = localtime(&t);

        char lbuffer[SIZE];
        snprintf(lbuffer, sizeof(lbuffer), "[%s][%d-%d-%d %d:%d:%d]", leveltostring(level).c_str(),
                 ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
                 ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

        va_list s;
        va_start(s, format);
        char rbuffer[SIZE];
        vsnprintf(rbuffer, sizeof(rbuffer), format, s);
        va_end(s);

        // 格式：默认部分（具体参数部分）+自定义部分（可变参数部分）
        char logtxt[SIZE * 2];
        snprintf(logtxt, sizeof(logtxt), "%s %s", lbuffer, rbuffer);

        printLog(level,logtxt);
    }

    ~Log()
    {}
private:
    int PrintMethod;
    string path;
};

// //可变参数至少要有一个具体的参数
// //因为要找起始地址
// int sum(int n,...)
// //参数要依次右→左压栈，形成栈帧结构
// {
//     va_list s;//char*
//     va_start(s,n);//s指向n的地址 &n
//     //va* 都是宏
//     int sum=0;
//     while(n--)
//     {
//         sum+=va_arg(s,int);
//     }
//     va_end(s);//s=NULL;
//     return sum;
// }